local addon = CreateFrame("Frame", "NinjaYell", UIParent)
addon.color = { r = 1, g = 1, b = 1 }
addon.ids = {}

local _G = getfenv(0)

local bit_bor = _G.bit.bor
local COMBATLOG_FILTER_ME = _G.COMBATLOG_FILTER_ME

local failSafe
local channel
local message
local target

local function print(msg) ChatFrame1:AddMessage("|cfffff468Ninja|rYell: "..msg) end
local function printf(...) print(format(...)) end

-- Spell DB, enter the spell you want announced in this table
-- Enter custom messages you want as shown below
-- Variables:
--	%t = Target's name
-- 	%m = Extra Info (for Missed, it's missType (i.e. Miss, Parry, Block, Dodge, etc.) for Interrupt it's the spell name that you interrupted)
-- Custom values:
--	Applied = Custom message(s) to use when this spell is APPLIED to your target
--	Faded = Custom message(s) to use when this spell is REMOVED from your target
--	Missed = Custom message(s) to use when this spell fails to hit for any reason
--	Interrupt = Custom message(s) to use when this spell INTERRUPTS another spell
--	Channel = Priority channel to use (this spell will ALWAYS use the specified channel)
--	Target = Whisper target (can be a function or a string, ONLY NEEDED if you used WHISPER as the priority channel)
addon.spells = {
	["Blind"] = {},
	["Taunt"] = {
		Applied = "",
		Faded = "",
		Missed = "Taunt failed on %t (%m). Now we're fucked.",
	},
	["Sap"] = {},
	["Kick"] = {},
	["Counterspell"] = {},
	["Pummel"] = {},
	["Polymorph"] = {
		Applied = "%t is sheeped. You break it, you tank it!",
		Faded = "%t's fleece is no longer as white as snow",
	},
	["Distract"] = {},
	["Cyclone"] = {},
	["Fear"] = {},
	["Psychic Scream"] = {},
	["Freezing Trap"] = {},
}

local function isMe(flags)
	return bit_bor(flags, COMBATLOG_FILTER_ME) == COMBATLOG_FILTER_ME
end

local function CLEU(self, event, time, eventType, srcGUID, srcName, srcFlags, destGUID, destName, destFlags, spellID, spellName, spellSchool, missType, extraSpellName)
	if ( not(addon.spells[spellName]) ) then return end
	
	if ( eventType == "SPELL_CAST_SUCCESS" or eventType == "SPELL_CAST_START" ) then
		--print(eventType)
		if ( isMe(srcFlags) ) then
			--printf("%s isMe", eventType)
			self:Scoop(spellName)
		end
	--[[
	elseif ( eventType == "SPELL_CAST_FAILED" ) then
		print(eventType)
		if ( failSafe == spellName ) then
			printf("%s failSafe passed, dumping", eventType)
			self:Dump()
		end
	--]]
	elseif ( eventType == "SPELL_AURA_APPLIED" ) then
		--print(eventType)
		if ( failSafe == spellName and addon.ids[destName] == destGUID ) then
			--printf("%s failSafe and GUID match found, dumping & announcing", eventType)	
			self:Announce(spellName, destName, 1)
			self:Dump()
			addon.spells[spellName].GUID = destGUID
			addon.spells[spellName].Active = true		
		else
			--printf("%s %s", failSafe, tostring(addon.ids[destName] == destGUID))
		end
	elseif ( eventType == "SPELL_INTERRUPT" ) then
		--print(eventType)
		if ( isMe(srcFlags) and failSafe == spellName and addon.ids[destName] == destGUID ) then
			--printf("%s isMe, failSafe and GUID match, announcing & dumping", eventType)
			self:Announce(spellName, destName, 4, extraSpellName)
			self:Dump()
		else
			--printf("%s %s %s", tostring(isMe(srcFlags)), failSafe, tostring(addon.ids[destName] == destGUID))
		end
	elseif ( eventType == "SPELL_MISSED" ) then
		--print(eventType)
		if ( isMe(srcFlags) ) then
			--printf("%s isMe", eventType)
			self:Announce(spellName, destName, 3, missType)
		else
			--printf("%s", tostring(isMe(srcFlags)))
		end
	elseif ( eventType == "SPELL_AURA_REMOVED" ) then
		--print(eventType)
		if ( addon.spells[spellName].Active and addon.spells[spellName].GUID == destGUID ) then
			--printf("%s Active and GUID match", eventType)
			self:Announce(spellName, destName, 2)
			addon.spells[spellName].GUID = false
			addon.spells[spellName].Active = false
		else
			--printf("%s %s", tostring(addon.spells[spellName].Active), tostring(addon.spells[spellName].GUID == destGUID))
		end
	elseif ( eventType == "UNIT_DIED" ) then
		--print(eventType)
		if ( addon.ids[destName] ) then
			self:Dump()
		end
	end
end

function addon:Scoop(spellName)
	failSafe = spellName
	for i, v in ipairs({"target", "focus", "mouseover"}) do
		if ( UnitExists(v) ) then
			addon.ids[UnitName(v)] = UnitGUID(v)
		end
	end
end

function addon:Dump()
	failSafe = nil
	for k, v in pairs(addon.ids) do
		addon.ids[k] = nil
	end
end

function addon:Announce(spellName, destName, index, ...)
	message = nil
	if ( index == 1 ) then
		if ( addon.spells[spellName].Applied ) then
			if ( type(addon.spells[spellName].Applied) == "string" ) then
				message = addon.spells[spellName].Applied:gsub("%%t", destName)
			else
				message = addon.spells[spellName].Applied[random(#addon.spells[spellName].Applied)]:gsub("%%t", destName)
			end
		else
			message = format("** %s on %s **", spellName, destName)
		end
	elseif ( index == 2 ) then
		if ( addon.spells[spellName].Faded ) then
			if ( type(addon.spells[spellName].Faded) == "string" ) then
				message = addon.spells[spellName].Faded:gsub("%%t", destName)
			else
				message = addon.spells[spellName].Faded[random(#addon.spells[spellName].Faded)]:gsub("%%t", destName)
			end
		else
			message = format("** %s faded from %s **", spellName, destName)
		end
	elseif ( index == 3 ) then
		if ( addon.spells[spellName].Missed ) then
			if ( type(addon.spells[spellName].Missed) == "string" ) then
				message = addon.spells[spellName].Missed:gsub("%%t", destName):gsub("%%m", ...)
			else
				message = addon.spells[spellName].Missed[random(#addon.spells[spellName].Missed)]:gsub("%%t", destName):gsub("%%m", ...)
			end
		else
			message = format("** %s failed on %s (%s) **", spellName, destName, ...)
		end
	elseif ( index == 4 ) then
		if ( addon.spells[spellName].Interrupt ) then
			if ( type(addon.spells[spellName].Interrupt) == "string" ) then
				message = addon.spells[spellName].Interrupt:gsub("%%t", destName):gsub("%%m", ...)
			else
				message = addon.spells[spellName].Interrupt[random(#addon.spells[spellName].Interrupt)]:gsub("%%t", destName):gsub("%%m", ...)
			end
		else
			message = format("** Interrupted %s's %s **", destName, ...)
		end
	end
	
	if ( not message ) then return end

	channel = nil
	if ( addon.spells[spellName].Channel ) then
		channel = addon.spells[spellName].Channel
	else
		if ( IsPartyLeader() ) then
			channel = "RAID_WARNING"
		elseif ( GetNumRaidMembers() > 0 and (select(2, IsInInstance()) ~= "pvp") ) then
			channel = "RAID"
		elseif ( GetNumPartyMembers() > 0 ) then
			channel = "PARTY"
		end
	end
	
	if ( not channel ) then
		if ( MikSBT and not(MikSBT.IsModDisabled()) ) then
			MikSBT.DisplayMessage(message, MikSBT.DISPLAYTYPE_NOTIFICATION, true, addon.color.r*255, addon.color.g*255, addon.color.b*255, nil, nil, nil, nil)
			return
		elseif ( SCT ) then
			SCT:DisplayMessage(message, addon.color)
			return
		elseif ( COMBAT_TEXT_SCROLL_FUNCTION ) then
			CombatText_AddMessage(message, COMBAT_TEXT_SCROLL_FUNCTION, addon.color.r, addon.color.g, addon.color.b, "crit", nil)
			return
		end
	elseif ( channel == "WHISPER" ) then
		target = addon.spells[spellName].Target
		if ( type(target) == "function" ) then
			target = target()
		end
		if ( target ) then
			SendChatMessage(message, "WHISPER", nil, target)
		end
		return
	end

	SendChatMessage(message, channel or "SAY")
end

function addon:Enable()
	self:SetScript("OnEvent", CLEU)
	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	print("Enabled")
end

function addon:Disable()
	self:SetScript("OnEvent", nil)
	self:UnregisterAllEvents()
	print("Disabled")
end

local function Toggle()
	if ( addon:IsEventRegistered("COMBAT_LOG_EVENT_UNFILTERED") ) then
		addon:Disable()
	else
		addon:Enable()
	end
end

SLASH_NYELL1 = "/nyell"
SlashCmdList["NYELL"] = Toggle

addon:Enable()